package my.dao.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.ClassUtils;

import javax.sql.DataSource;
import javax.transaction.TransactionManager;

@Configuration
@EnableJpaRepositories(basePackages = {"my.database.test.repository"},
		entityManagerFactoryRef = "testEntityManagerFactory",
		transactionManagerRef = "testTransactionManager")
public class TestDataSourceConfiguration {
	@Autowired
	ApplicationContext applicationContext;
	@Autowired
    private JpaProperties jpaProperties;
	
	@Bean
	@ConditionalOnMissingBean
	@ConfigurationProperties(prefix="spring.datasource.test")
	public DataSource testDataSource() {
		final String[] DATA_SOURCE_TYPE_NAMES = new String[] {
				"com.alibaba.druid.pool.DruidDataSource",
				"org.apache.commons.dbcp2.BasicDataSource",
				"org.apache.tomcat.jdbc.pool.DataSource",
				 };
		return new DataSourceBuilder(applicationContext.getClassLoader()) {
			@Override
			@SuppressWarnings("unchecked")
			public Class<? extends DataSource> findType() {
				for (String name : DATA_SOURCE_TYPE_NAMES) {
					try {
						return (Class<? extends DataSource>) ClassUtils.forName(name, applicationContext.getClassLoader());
					}
					catch (Exception ex) {
						// Swallow and continue
					}
				}
				return null;
			}
		}.build();
	}
	
	
	@Bean
	@ConditionalOnMissingBean
	public LocalContainerEntityManagerFactoryBean testEntityManagerFactory(EntityManagerFactoryBuilder builder) {
		DataSource db = testDataSource();
		return builder.dataSource(db)
				.packages("my.database.test.entity")
				.properties(jpaProperties.getHibernateProperties(db))
				.build();
	}
	
	@Bean
	@ConditionalOnMissingBean
	public PlatformTransactionManager testTransactionManager(EntityManagerFactoryBuilder builder) {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		transactionManager.setEntityManagerFactory(testEntityManagerFactory(builder).getObject());
		return transactionManager;
	}
}
